package ru.adhoc.truealarm.player;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.util.Log;

import java.io.IOException;

import ru.adhoc.truealarm.R;
import ru.adhoc.truealarm.db.DbHelper;
import ru.adhoc.truealarm.utils.Util;
import ru.adhoc.truealarm.vibrator.Vibro;


/**
 * Created by Малюгин Сергей on 22.07.13.
 */
public class SoundPlayer implements SensorEventListener {

    static SoundPlayer instance;
    private Context context;
    private MediaPlayer mediaPlayer;
    private DbHelper DbHelper;
    private Vibro v;
    private Thread t;
    private SensorManager sm;

    private final AudioManager mAudioManager;
    private final int originalVolume;
    private final int maxVolume;

    private boolean ifAlarm;

    private float x = 0;
    private float y = 0;
    private float z = 0;

    private int i;


    public SoundPlayer(Context c)  {
        context = c;
        v = Vibro.getInstance(context);
        mAudioManager = (AudioManager)context.getSystemService(context.AUDIO_SERVICE);
        originalVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
    }

    public static SoundPlayer getInstance(Context ctx){
        if (instance == null){
            instance = new SoundPlayer(ctx);
        }
        return instance;
    }

    public void playSound(Uri uri, int id, boolean alarm){

        ifAlarm = alarm;

        //Будем провверять ури на наличие файла и если его нет заменять на мелдию по умолчанию
        if(!Util.getInstance(context).uriFileExist(uri))
            uri = Uri.parse("android.resource://ru.adhoc.truealarmfree/" + R.raw.nature);

        if (mediaPlayer != null){
            mediaPlayer.stop();
            mediaPlayer.reset();
            mediaPlayer.release();
            mediaPlayer = null;
        }

        mediaPlayer = new MediaPlayer();

        try {
            mediaPlayer.setDataSource(context, uri);
        } catch (IOException e) {
            e.printStackTrace();
        }

        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);

        try {
            mediaPlayer.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }

        if(alarm)
        mediaPlayer.setLooping(true);

        if(!mediaPlayer.isPlaying()){

            runAccelerometerListener();

            mediaPlayer.start();

            increaseVolume();
            if(getVibrate(id) && alarm){
                v.startVibro();
            }
        }
    }

    private void runAccelerometerListener() {

        sm = (SensorManager)context.getSystemService(context.SENSOR_SERVICE);
        if(sm.getSensorList(Sensor.TYPE_ACCELEROMETER).size()!=0){
            Sensor s = sm.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
            sm.registerListener(this,s, SensorManager.SENSOR_DELAY_NORMAL);
        }

    }

    public void stopPlaySound(){

        if(mediaPlayer != null && mediaPlayer.isPlaying()){
            mediaPlayer.stop();
            mediaPlayer.reset();
            mediaPlayer.release();
            mediaPlayer = null;
            mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, originalVolume, 0);

            sm.unregisterListener(this);

            if(t != null && t.isAlive())
            t.interrupt();
        }
        if(v != null)v.stopVibro();
    }

    private boolean getVibrate(int id){

        DbHelper = DbHelper.getInstance(context);
        SQLiteDatabase db = DbHelper.getWritableDatabase();
        int vib = 1;

        try{
            Cursor c = DbHelper.getOnesAlarm(db, id);
            if(c.moveToFirst()){
                vib = c.getInt(c.getColumnIndex("vibrate"));
                c.close();
            }
        }
        finally {
            if(db != null)
                db.close();
        }

        if(vib !=1)
            return false;
        else
            return true;
    }

    private void increaseVolume(){

        if(ifAlarm){
            t = new Thread(
                    new Runnable() {
                        @Override
                        public void run() {
                            for (i = 0; i <= maxVolume; i++) {

                                try {
                                    mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, i, 0);
                                    t.sleep(1 * 1000);
                                } catch (InterruptedException e) {
                                    Log.e("My", "increase failure");
                                }
                            }
                        }
                    }
            );
            t.start();
        }
        else {
            mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, originalVolume, 0);
        }
    }

    @Override
    public void onSensorChanged(SensorEvent sensorEvent) {

        if(ifAlarm && sensorEvent.sensor.getType()==Sensor.TYPE_ACCELEROMETER){

            float xnew = sensorEvent.values[0];
            float ynew = sensorEvent.values[1];
            float znew = sensorEvent.values[2];

            if(x==0 && y == 0 && z ==0){
                x = xnew;
                y = ynew;
                z = znew;
            }

            float xdif = normalizeFloat(x-xnew);
            float ydif = normalizeFloat(y-ynew);
            float zdif = normalizeFloat(z-znew);

            if(xdif > 3 || ydif > 3 || zdif > 3){
                if(t != null && t.isAlive())
                    i =2;
                else
                    increaseVolume();
                x = xnew;
                y = ynew;
                z = znew;
            }
        }

    }

    private float normalizeFloat(float q){
        if(q < 0)
          q = q*(-1);
        return q;
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int i) {

    }
}
